home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / dict / _rb_tree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  4.9 KB  |  179 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _rb_tree.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15. #include <LEDA/impl/rb_tree.h>
  16.  
  17.  
  18. //----------------------------------------------------------------------------
  19. //  rb_tree:
  20. //
  21. //  rebalancing routines for red black trees
  22. //
  23. //----------------------------------------------------------------------------
  24.  
  25.  
  26. void rb_tree::insert_rebal(rb_tree_item v)
  27. {
  28.   // preconditions:  v is new node created by insertion
  29.   //                 v != root
  30.   //
  31.   //                    u
  32.   //                    |
  33.   //                    v
  34.   //                   / \
  35.   //                  x   y
  36.   //
  37.  
  38.   rb_tree_item u = v->parent;
  39.  
  40.   while (u->get_bal() == red)
  41.   {
  42.     int dir = (v == u->child[left]) ? left : right;
  43.  
  44.     rb_tree_item p = u->parent; 
  45.     int dir1 = (u == p->child[left]) ? left : right;
  46.  
  47.     rb_tree_item w = p->child[1-dir1];
  48.  
  49.     if ( w->get_bal() == red )    // p has two red children (u and w)
  50.        { u->set_bal(black);
  51.          w->set_bal(black);
  52.          if (p == root())  
  53.          { p->set_bal(black); 
  54.            break; 
  55.           }
  56.          p->set_bal(red);
  57.          v = p;
  58.          u = p->parent;
  59.         }
  60.     else 
  61.        if (dir1 == dir)      // rebalancing by one rotation
  62.          { rotation(p,u,dir1);
  63.            p->set_bal(red);
  64.            u->set_bal(black);
  65.            break;
  66.           }       
  67.        else
  68.         { double_rotation(p,u,v,dir1);
  69.           p->set_bal(red);
  70.           v->set_bal(black);
  71.           break;
  72.          }
  73.    }
  74.  
  75. }
  76.  
  77.  
  78.  
  79. void rb_tree::del_rebal(rb_tree_item w, rb_tree_item p)
  80. {
  81.   // precondition:    p is removed inner node
  82.   //                  w is remaining child of p (already linked to parent u)
  83.   //                  w != root
  84.  
  85.  
  86.  
  87.   if (p->get_bal()==red) return;  // case 1 : nothing to do
  88.  
  89.   if (w->get_bal()==red)          // case 2
  90.   { w->set_bal(black); 
  91.     return; 
  92.    } 
  93.  
  94.  
  95.   rb_tree_item u = w->parent;
  96.   int dir = (w == u->child[left]) ? left : right;
  97.  
  98.   while (true)
  99.   {
  100.     rb_tree_item w = u->child[1-dir];
  101.   
  102.     // situation: black height of subtree rooted at black node 
  103.     // v = u->child[dir] is by one too small, w = sibling of v
  104.     //
  105.     // => increase black height of v or "move" v towards the root
  106.     //
  107.     //                          |                         |
  108.     //                          u                         u
  109.     //           dir=left:     / \        dir=right:     / \
  110.     //                        /   \                     /   \
  111.     //                       v     w                   w     v
  112.     //                            / \                 / \
  113.     //                           /   \               /   \
  114.     //                          y     x             x     y
  115.    
  116.   
  117.     if ( w->get_bal()==black )                    // case 2: v and w are black
  118.       { rb_tree_item y = w->child[1-dir];
  119.         if ( y->get_bal()==red )                  // case 2.b 
  120.            { rotation(u,w,1-dir);
  121.              w->set_bal(u->get_bal());
  122.              u->set_bal(black);
  123.              y->set_bal(black);
  124.              break;
  125.             }
  126.         else   
  127.            if ( (y=w->child[dir])->get_bal()==red ) // case 2.c 
  128.               { double_rotation(u,w,y,1-dir);
  129.                 y->set_bal(u->get_bal());
  130.                 u->set_bal(black);
  131.                 break;
  132.               }
  133.            else 
  134.               if ( u->get_bal()==red )     // case 2.a2
  135.                  { w->set_bal(red);
  136.                    u->set_bal(black);
  137.                    break; 
  138.                   }
  139.               else                        // case 2.a1
  140.                  { rotation(u,w,1-dir);
  141.                    u->set_bal(red);
  142.                    if ( w == root() )
  143.                       break;
  144.                    else // the only non-terminating case
  145.                       { u = w->parent;
  146.                         dir = (w == u->child[left]) ? left : right;
  147.                        }
  148.                   }
  149.       }     
  150.     else                                  // case 3: v ist black, w ist red
  151.       { rb_tree_item x = w->child[dir];
  152.         rb_tree_item y;
  153.         if ( x->child[1-dir]->get_bal()==red )          // case 3.b
  154.           { double_rotation(u,w,x,1-dir);
  155.             w->child[dir]->set_bal(black);
  156.             break;
  157.            }
  158.         else 
  159.            if ( (y = x->child[dir])->get_bal()==red )   // case 3.c
  160.              { rotation(x,y,dir);
  161.                w->child[dir] = y; 
  162.                double_rotation(u,w,y,1-dir);
  163.                y->set_bal(black);
  164.                break;
  165.               }
  166.            else                                     // case 3.a 
  167.              { rotation(u,w,1-dir);
  168.                w->set_bal(black);
  169.                x->set_bal(red);
  170.                break;
  171.               }
  172.        }
  173.   
  174.    } /* end of loop */
  175.  
  176. }
  177.  
  178.